/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.kramerius4.resolver;

import cz.mzk.kramerius4.resolver.dom4jutils.Dom4jUtils;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.XPath;

/**
 *
 * @author Martin Řehánek <rehan at mzk.cz>
 */
public class IdMapper {

    private static final Logger logger = Logger.getLogger(IdMapper.class.getName());
    private static final XPath K3_HANDLE_PATH = DocumentHelper.createXPath("k3Handle");
    private static final XPath K3_SIGLA_PATH = DocumentHelper.createXPath("sigla");
    private static final XPath K3_NUMBER_PATH = DocumentHelper.createXPath("number");
    private static final XPath K4_UUID_PATH = DocumentHelper.createXPath("k4Uuid");
    private Map<K3Identifier, String> k3idUuidMap = new HashMap<K3Identifier, String>();

    private IdMapper(){};

    public IdMapper(File mappingFile) throws DocumentException, IOException {
        loadMappings(mappingFile);
    }

    private void loadMappings(File mappingFile) throws DocumentException, IOException {
        Document doc = Dom4jUtils.loadDocument(mappingFile, false);
        List<Element> elements = doc.selectNodes("/mappings/mapping");
        for (Element mappingEl : elements) {
            loadMapping(mappingEl);
        }
    }

    private void loadMapping(Element mappingEl) {
        Element k3HandleEl = (Element) K3_HANDLE_PATH.selectSingleNode(mappingEl);
        K3Identifier k3Handle = findK3Id(k3HandleEl);
        Element k4UuidEl = (Element) K4_UUID_PATH.selectSingleNode(mappingEl);
        String k4Uuid = findK4Uuid(k4UuidEl);
        if (k3Handle == null && k4Uuid == null) {
            logger.log(Level.WARNING, "incorrect content of some mapping in mapping file");
        } else if (k3Handle == null) {
            logger.log(Level.WARNING, "cannot find kramerius 3 handle for kramerius 4 uuid: {0}", (k4Uuid == null ? null : k4Uuid));
        } else if (k4Uuid == null) {
            logger.log(Level.WARNING, "cannot find kramerius 4 uuid for kramerius 3 handle: {0}", (k3Handle == null ? null : k3Handle));
        } else {
            updateMapping(k3Handle, k4Uuid);
        }
    }

    private K3Identifier findK3Id(Element k3HandleEl) {
        if (k3HandleEl == null) {
            logger.log(Level.WARNING, "missing element k3Handle");
            return null;
        }
        Element siglaEl = (Element) K3_SIGLA_PATH.selectSingleNode(k3HandleEl);
        if (siglaEl == null) {
            logger.log(Level.WARNING, "sigla missing");
            return null;
        }
        Element numberEl = (Element) K3_NUMBER_PATH.selectSingleNode(k3HandleEl);
        if (numberEl == null) {
            logger.log(Level.WARNING, "number missing");
            return null;
        }
        return new K3Identifier(siglaEl.getText(), numberEl.getText());
    }

    private String findK4Uuid(Element k4UuidEl) {
        if (k4UuidEl == null) {
            logger.log(Level.WARNING, "missing element k4Uuid");
            return null;
        }
        return k4UuidEl.getText();
    }

    private void updateMapping(K3Identifier k3Handle, String k4Uuid) {
        String presentValue = k3idUuidMap.get(k3Handle);
        if (presentValue != null) {
            logger.log(Level.SEVERE, "multiple values found for {0}: {1} and {2}", new Object[]{k3Handle, presentValue, k4Uuid});
        }
        k3idUuidMap.put(k3Handle, k4Uuid);
    }

    public String findUuid(K3Identifier k3Id) {
        return k3idUuidMap.get(k3Id);
    }
}
